<template>
	<view class="main">
		<view class="return" @click="toReturn()" style="box-shadow: 1rpx 2rpx 4rpx 2rpx gainsboro;">
			<u-icon name="arrow-left" size="20"></u-icon>
		</view>
		<image src="/static/bg3.png" class="bg"></image>
		<view class="search">
			<u-search bgColor="#ffffff" placeholder="输入搜索内容" :showAction="false" v-model="keyword"
				@change="toChange()"></u-search>
		</view>
		<image :src="banner" mode="widthFix" class="banner"></image>
		<u-tabs :current="currentIndex" :list="routeList" :scrollable="false" @click="click" :activeStyle="activeStyle"
			lineColor="#00AF91"></u-tabs>
		<!-- https://gxtravel.ncscloudmedia.com/uploads/png/20250826/f283d015af6da054e639ae53929ef1a1.png -->
		<scroll-view v-if="routeList2.length!=0" :scroll-x="true" :scroll-left="scrollLeft" scroll-with-animation
			class="u-tabs__wrapper__scroll-view categoryList" :show-scrollbar="false"
			ref="u-tabs__wrapper__scroll-view">
			<!-- <view class="categoryList"> -->
			<!-- <view class="category-item" :class="category_id==''?'category-item-a':''">全部</view> -->
			<view @click="toClick(item.id,index)" class="category-item"
				:class="[category_id==item.id?'category-item-a':'',`u-tabs__wrapper__nav__item-${index}`]"
				v-for="(item,index) in routeList2" :key="index">
				<image :src="item.icon"></image>
				<span>{{item.name}}</span>
			</view>
			<!-- </view> -->
		</scroll-view>
		<view @click="toUrl(item.id,item.is_jump,item.jump_app_type)" class="list" v-for="(item,index) in list" :key="index">
			<image :src="item.cover" mode="aspectFill"></image>
			<view class="infos">
				<view class="title">{{item.name}}</view>
				<view class="flex time" v-if="item.open_time!=''">
					<u-icon name="clock-fill"></u-icon>
					<view>{{item.open_time}}
					</view>
				</view>
				<view class="flex time">
					<u-icon name="map-fill"></u-icon>
					<view>{{item.address}}</view>
				</view>
			</view>
		</view>
		<xw-empty :isShow="empty" text="暂无数据" textColor="#777777"></xw-empty>
		<!-- 返回顶部按钮 -->
		<view class="back-to-top" v-if="showBack" @click="handleTop">
			<image src="/static/top.png" mode="widthFix"></image>
		</view>
	</view>
</template>

<script>
	import wx from 'weixin-js-sdk'
	import {
		culturalList,
		culturalCategory,
		positionDetail
	} from '@/api/apiData.js';
	export default {
		data() {
			return {
				scrollLeft: 0,
				banner: '',
				keyword: '',
				totalPage: 1,
				page: 0,
				offset: 10,
				list: [],
				scrollTop: 0,
				empty: false,
				loadText: {
					loadmore: '点击或上拉加载更多',
					loading: '努力加载中',
					nomore: '实在没有了'
				},
				activeStyle: {
					color: '#00AF91',
				},
				status: 'loadmore',
				category_id: '',
				routeList: [{
					id: '',
					name: '全部',
				}],
				routeList2: [],
				currentIndex: 0,
				parent_id: '',
				innerCurrent: 0,
				showBack: false,
				ws: null,
				path: '/pages/cultural/cultural',
				isMiniprogram:false
			};
		},
		onPageScroll(e) {
			const that = this;
			that.scrollTop = e.scrollTop;
			// 监听页面滚动事件
			if (e.scrollTop >= 100) {
				this.showBack = true; // 滚动距离超过100px时显示返回顶部按钮
			} else {
				this.showBack = false; // 否则隐藏返回顶部按钮
			}
		},
		onReachBottom() {
			const that = this;
			that.getlist();
		},
		onLoad() {
			this.getBanner()
			this.getCategory()
			this.getlist()
		},
		onShow() {
			this.connectWebSocket()
		},
		onShareAppMessage(){
			
		},
		onHide() {
			// 页面隐藏/切入后台时触发
			let that = this
			this.sendData({
				type: 'page_leave',
				path: that.path,
				params: ""
			});
		},
		onUnload() {
			// 页面卸载时触发
			let that = this
			that.sendData({
				type: 'page_leave',
				path: that.path,
				params: ""
			});
		},
		methods: {
			toUrl(id,is_jump,jump_app_type) {
				if(is_jump==1&&jump_app_type==1){
					if(this.isMiniprogram){
						 wx.miniProgram.getEnv(function (result) {
						        if (result.miniprogram) {
						          wx.miniProgram.navigateTo({
						            url: "/pages/detail/detail?id="+id,
						          });
						        }
						      });
					}else{
						uni.navigateTo({
							url: '/pages/cultural/detail?id=' + id
						})
					}
				}else{
					uni.navigateTo({
						url: '/pages/cultural/detail?id=' + id
					})
				}
				
			},
		// 连接
		connectWebSocket() {
			let that = this
			const wsUrl = "wss://gxtravel.ncscloudmedia.com/wss"; // 确保使用wss（WebSocket Secure）如果服务器支持
			uni.connectSocket({
				url: wsUrl,
				success: function(res) {
					console.log('WebSocket连接成功');
					that.sendData({
						type: 'page_enter',
						path: that.path,
						params: ""
					});
				},
				fail: function(err) {
					console.error('WebSocket连接失败', err);
				}
			});
		},
		// 发送
		sendData(data) {
			uni.sendSocketMessage({
				data: JSON.stringify(data),
				success: function(res) {
					console.log('消息发送成功');
				},
				fail: function(err) {
					console.error('消息发送失败', err);
				}
			});
		},
			handleTop() {
				uni.pageScrollTo({
					scrollTop: 0, // 滚动到页面顶部
					duration: 300 // 滚动动画持续时间，单位为毫秒
				});
			},
			setLineLeft() {
				const tabItem = this.list[this.innerCurrent];
				if (!tabItem) {
					return;
				}
				// 获取滑块该移动的位置
				let lineOffsetLeft = this.list
					.slice(0, this.innerCurrent)
					.reduce((total, curr) => total + curr.rect.width, 0);
				// 获取下划线的数值px表示法
				const lineWidth = uni.$u.getPx(this.lineWidth);
				this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2
				// #ifdef APP-NVUE
				// 第一次移动滑块，无需过渡时间
				this.animation(this.lineOffsetLeft, this.firstTime ? 0 : parseInt(this.duration))
				// #endif

				// 如果是第一次执行此方法，让滑块在初始化时，瞬间滑动到第一个tab item的中间
				// 这里需要一个定时器，因为在非nvue下，是直接通过style绑定过渡时间，需要等其过渡完成后，再设置为false(非第一次移动滑块)
				if (this.firstTime) {
					setTimeout(() => {
						this.firstTime = false
					}, 10);
				}
			},
			setScrollLeft() {
				// 当前活动tab的布局信息，有tab菜单的width和left(为元素左边界到父元素左边界的距离)等信息
				const tabRect = this.routeList2[this.innerCurrent]
				// 累加得到当前item到左边的距离
				const offsetLeft = this.routeList2
					.slice(0, this.innerCurrent)
					.reduce((total, curr) => {
						return total + curr.rect.width
					}, 0)
				// 此处为屏幕宽度
				const windowWidth = uni.$u.sys().windowWidth
				// 将活动的tabs-item移动到屏幕正中间，实际上是对scroll-view的移动
				let scrollLeft = offsetLeft - (this.tabsRect.width - tabRect.rect.width) / 2 - (windowWidth - this.tabsRect
					.right) / 2 + this.tabsRect.left / 2
				// 这里做一个限制，限制scrollLeft的最大值为整个scroll-view宽度减去tabs组件的宽度
				scrollLeft = Math.min(scrollLeft, this.scrollViewWidth - this.tabsRect.width)
				this.scrollLeft = Math.max(0, scrollLeft)
			},
			// 获取所有标签的尺寸
			resize() {
				// 如果不存在list，则不处理
				if (this.routeList2.length === 0) {
					return
				}
				Promise.all([this.getTabsRect(), this.getAllItemRect()]).then(([tabsRect, itemRect = []]) => {
					this.tabsRect = tabsRect
					this.scrollViewWidth = 0
					itemRect.map((item, index) => {
						// 计算scroll-view的宽度，这里
						this.scrollViewWidth += item.width
						// 另外计算每一个item的中心点X轴坐标
						this.routeList2[index].rect = item
					})
					// 获取了tabs的尺寸之后，设置滑块的位置
					this.setLineLeft()
					this.setScrollLeft()
				})
			},
			// 获取导航菜单的尺寸
			getTabsRect() {
				return new Promise(resolve => {
					this.queryRect('u-tabs__wrapper__scroll-view').then(size => resolve(size))
				})
			},
			// 获取所有标签的尺寸
			getAllItemRect() {
				return new Promise(resolve => {
					const promiseAllArr = this.routeList2.map((item, index) => this.queryRect(
						`u-tabs__wrapper__nav__item-${index}`, true))
					Promise.all(promiseAllArr).then(sizes => resolve(sizes))
				})
			},
			// 获取各个标签的尺寸
			queryRect(el, item) {
				// #ifndef APP-NVUE
				// $uGetRect为uView自带的节点查询简化方法，详见文档介绍：https://www.uviewui.com/js/getRect.html
				// 组件内部一般用this.$uGetRect，对外的为uni.$u.getRect，二者功能一致，名称不同
				return new Promise(resolve => {
					this.$uGetRect(`.${el}`).then(size => {
						resolve(size)
					})
				})
				// #endif

				// #ifdef APP-NVUE
				// nvue下，使用dom模块查询元素高度
				// 返回一个promise，让调用此方法的主体能使用then回调
				return new Promise(resolve => {
					dom.getComponentRect(item ? this.$refs[el][0] : this.$refs[el], res => {
						resolve(res.size)
					})
				})
				// #endif
			},
			async getBanner() {
				const result = await positionDetail({
					position_id: 32
				})
				if (result.code == 1) {
					this.banner = result.data.path
				} else {
					uni.showToast({
						title: result.msg,
						icon: 'error'
					});
				}
			},
			click(e) {
				console.log(e)
				this.routeList2 = []
				this.scrollLeft = 0
				if (e.id != '') {
					this.getCategory2(e.id)
				}
				this.category_id = e.id
				this.page = 0
				this.list = []
				this.getlist()
			},
			toClick(id, i) {
				this.category_id = id
				this.innerCurrent = i
				this.page = 0
				this.list = []
				this.getlist()
				this.resize()
				// this.scrollLeft = i * 100;
				console.log(this.scrollLeft)
			},
			async getCategory() {
				const result = await culturalCategory({
					parent_id: this.parent_id
				})
				if (result.code == 1) {
					this.routeList = this.routeList.concat(result.data)
				} else {
					uni.showToast({
						title: result.msg,
						icon: 'error'
					});
				}
			},
			async getCategory2(id) {
				const result = await culturalCategory({
					parent_id: id
				})
				if (result.code == 1) {
					if (result.data.length > 0) {
						this.routeList2 = this.routeList2.concat(result.data)

					} else {
						this.routeList2 = []
					}
				} else {
					uni.showToast({
						title: result.msg,
						icon: 'error'
					});
				}
			},
			toChange() {
				this.page = 0
				this.list = []
				this.getlist()
			},
			toReturn() {
				uni.navigateBack()
			},
			async getlist() {
				const that = this;
				const {
					totalPage,
					page,
					offset,
					list,
					keyword,
					category_id
				} = that;
				let obj = {
					size: offset,
					page: page + 1,
					name: keyword,
					category_id
				};
				that.status = 'loading';
				if (totalPage > page) {
					let result = await culturalList(obj);
					if (result.code == 1) {
						that.page = page + 1;
						if (result.data.total == 0) {
							that.empty = true;
							that.status = 'nomore';
							return;
						}
						that.empty = false;
						setTimeout(() => {
							that.status = 'loadmore';
						}, 500);
						that.list = list.concat(result.data.list);
						that.totalPage = Math.ceil(result.data.total / offset);
					}
				} else {
					setTimeout(() => {
						that.status = 'nomore';
					}, 500);
				}
			},
		}
	}
</script>

<style lang="scss" scoped>
	page {
		padding-bottom: 100rpx;
		// background: #F6F7FB;
	}

	.banner {
		width: 100%;
		height: 200rpx;
		margin-top: 32rpx;
	}

	.bg {
		position: fixed;
		width: 100%;
		height: 100%;
		top: 0;
		left: 0;
		z-index: -1;
	}

	.categoryList {
		white-space: nowrap;
		padding: 15rpx 0 0rpx;
		height: 80rpx;

		.category-item {
			display: inline-block;
			margin-right: 16rpx;
			font-size: 28rpx;
			padding: 8rpx 24rpx;
			border-radius: 56rpx;
			background: white;
			box-shadow: 1rpx 1rpx 2rpx 1rpx gainsboro;

			image {
				width: 34rpx;
				height: 36rpx;
				margin-right: 10rpx;
				position: relative;
				top: 4rpx;
			}
		}

		.category-item-a {
			background: #00AF91;
			color: white;
		}
	}

	.main {
		padding-top: 80rpx;
		margin: 0 30rpx;

		.search {
			box-shadow: 1rpx 2rpx 10rpx 1rpx gainsboro;
			border-radius: 50rpx;
			width: 100%;
			margin-top: 100rpx;
		}

		.list {
			border-radius: 16rpx;
			background: white;
			box-shadow: 1rpx 2rpx 10rpx 1rpx gainsboro;
			margin-top: 30rpx;

			image {
				border-radius: 16rpx 16rpx 0rpx 0rpx;
				height: 336rpx;
				width: 100%;
			}

			.infos {
				padding: 16rpx;

				.title {
					font-size: 32rpx;
					margin-bottom: 16rpx;
				}

				.time {
					color: #6C7A94;
					font-size: 24rpx;
					margin-bottom: 6rpx;

					view {
						margin-right: 6rpx;
					}
				}
			}
		}
	}
</style>